rewrite strip_nastyhtml, strip_html in Qt (#1341)
authortsteven4 <13596209+tsteven4@users.noreply.github.com>
Mon, 23 Sep 2024 20:06:08 +0000 (14:06 -0600)
committerGitHub <noreply@github.com>
Mon, 23 Sep 2024 20:06:08 +0000 (14:06 -0600)
* rewrite strip_html with QString.

* rewrite strip_nasty_html in Qt.

and actually produce valid html:
1. the replacement for "<body>", "<!   >", is invalid.
2. leaving an html tag in causes the html format output to be invalid.

* cleanup comment xstrdup

* use regex for strip_html

* strip_html deletes other tags

* fix strip_html img tag handling

* Revert "fix strip_html img tag handling"

This reverts commit b0440f7e3729909fd51ecbbacdd7a7e4aa5d9198.

* Revert "strip_html deletes other tags"

This reverts commit 40fe2ef0153d8c2e6d53432b9184f8acffbab2ef.

* Revert "use regex for strip_html"

This reverts commit 677da95a77b335bfa686a35fc33e862f8b50f053.

* implement strip_html using QRegularExpressionMatchIterator.

* a little cleanup

* remove obsolete include

* take care to distinguish tags with common roots

like p, param, pre.

* suppress InvalidReads in qhash.

These are known to occur per comment in qhash.cpp.

* supress qhash false positive with libqt6core6/jammy-updates,now 6.2.4+dfsg-2ubuntu1.1 amd64

* suppress vg warnings on noble (intermittant).

* install qt core dbgsyms for valgrind suppression.

* kill space preceding newline when stripping html.

* use modernize-raw-string-literal

* valgrind suppressions for f40

* add symbols for fedora valgrind suppression.

17 files changed:
exif.cc
gpsbabel.supp
reference/gc/GC7FA4.text
reference/gc/GCGCA8-encoded.txt
reference/gc/GCGCA8.txt
reference/gc/GCGCA8_nasty.gpx [new file with mode: 0644]
reference/gc/GCGCA8_nasty.html [new file with mode: 0644]
reference/gc/GCGCA8~vcard.vcf
testo
testo.d/text.test
tools/Dockerfile_f37
tools/Dockerfile_f38
tools/Dockerfile_f39
tools/Dockerfile_f40
tools/Dockerfile_jammy
tools/Dockerfile_noble
util.cc

diff --git a/exif.cc b/exif.cc
index cece53d16fd4daa9253833fcaad3fefd2ff68ec2..8cf300fdabec2d352df309a22f8529969f60b43b 100644 (file)
--- a/exif.cc
+++ b/exif.cc
@@ -63,7 +63,7 @@
 #include <cstring>              // for memcmp, strlen
 #include <utility>              // for as_const
 
-#include "defs.h"               // for Waypoint, fatal, warning, global_options, global_opts, unknown_alt, xfree, route_disp_all, track_disp_all, waypt_disp_all, wp_flags, KNOTS_TO_MPS, KPH_TO_MPS, MPH_TO_MPS, MPS_TO_KPH, WAYPT_HAS, case_ignore_strcmp, waypt_add, xstrdup, fix_2d
+#include "defs.h"               // for Waypoint, fatal, warning, global_options, global_opts, unknown_alt, xfree, route_disp_all, track_disp_all, waypt_disp_all, wp_flags, KNOTS_TO_MPS, KPH_TO_MPS, MPH_TO_MPS, MPS_TO_KPH, WAYPT_HAS, case_ignore_strcmp, waypt_add, fix_2d
 #include "garmin_tables.h"      // for gt_lookup_datum_index
 #include "gbfile.h"             // for gbfputuint32, gbfputuint16, gbfgetuint16, gbfgetuint32, gbfseek, gbftell, gbfile, gbfclose, gbfcopyfrom, gbfwrite, gbfopen_be, gbfread, gbfrewind, gbfgetflt, gbfgetint16, gbfopen, gbfputc, gbfputflt, gbsize_t, gbfeof, gbfgetdbl, gbfputdbl, gbfile::(anonymous)
 #include "jeeps/gpsmath.h"      // for GPS_Math_WGS84_To_Known_Datum_M
index e91a05fac1f3aebe933aa57f83c923117034a9f3..3cbfa1e70de71be5f37eafe59edc367c3b429f05 100644 (file)
@@ -1,3 +1,39 @@
+{
+   <Fedora 40 vtesto text, qt6-qtbase.x86_64 6.7.2-6.fc40 intermittant>
+   Memcheck:Addr16
+   fun:UnknownInlinedFun
+   fun:aeshash128_lt16
+   fun:_ZL10aeshash128PKhmmm
+   fun:calculateHash<QStringView>
+}
+{
+   <Ubnutu jammy vtesto text, libqt6core6/jammy-updates,now 6.2.4+dfsg-2ubuntu1.1 amd64 >
+   Memcheck:Addr16
+   fun:UnknownInlinedFun
+   fun:_ZL7aeshashPKhmm
+   fun:calculateHash<QStringView>
+}
+{
+   <Ubuntu noble vtesto text, libqt6core6t64/noble,now 6.4.2+dfsg-21.1build5 amd64>
+   Memcheck:Addr16
+   fun:UnknownInlinedFun
+   fun:_ZL15aeshash128_lt16Dv2_xPKhm
+}
+{
+   <Ubuntu Jammy vtesto text, qtio qhash.cpp 6.2.4>
+   Memcheck:Addr16
+   fun:_mm_loadu_si128
+   fun:_ZL7aeshashPKhmm
+   fun:calculateHash<QStringView>
+}
+{
+   <Ubuntu Jammy vtesto text, qtio qhash.cpp 6.7.2 intermittant>
+   Memcheck:Addr16
+   fun:_mm_loadu_si128
+   fun:aeshash128_lt16
+   fun:_ZL10aeshash128PKhmmm
+   fun:calculateHash<QStringView>
+}
 {
    <Fedora18: Qt's use of libuuc leaks.>
    Memcheck:Leak
index 51dfba954cec02f6acad3003f5180dddfe79cae7..90b1d9c6a0c757f347a03e304811e811a02ba013 100644 (file)
@@ -4,18 +4,18 @@ Points géodésiques du Québec by Sverdrup2 - Locationless (Reverse) Cache / Vi
 
 LES COORDONÉES PUBLIÉES NE REPRÉSENTENT PAS LA LOCALISATION D'UNE CACHE PUBLISHED COORDINATES DO NOT REPRESENT THE LOCALIZATION OF A CACHE
 
-Le but de cette cache virtuelle est de trouver les points géodésiques du territoire québécois. Les points géodésiques sont faciles à identifier (capuchons de laiton au niveau du sol). Généralement, il y a un panneau de couleur orange sur un poteau à proximité du point. Sur ce panneau, le numéro du point est identifié. Aussi, la distance relative du panneau au point est indiquée.  
+Le but de cette cache virtuelle est de trouver les points géodésiques du territoire québécois. Les points géodésiques sont faciles à identifier (capuchons de laiton au niveau du sol). Généralement, il y a un panneau de couleur orange sur un poteau à proximité du point. Sur ce panneau, le numéro du point est identifié. Aussi, la distance relative du panneau au point est indiquée. 
  Pour inscrire votre découverte, vous devez prendre en note le NUMÉRO DU POINT(inscrit sur le point même ou au centre du panneau)LA COORDONNÉE(en format HDDD MM.MM WGS84 datum ET UTM NAD83 indiquer la zone SVP)et L'ALTITUDE RELATIVE. Si le points n'est pas visible (il se peut qu'il soit sous quelques centimètres de terre) vous pouvez prendre la coordonnée à l'emplacement du panneau SI LA PRÉCISION DE VOTRE GPS EST SUPÉRIEUR À LA DISTANCE INSCRITE SUR LE PANNEAU (ex : Précison du GPS de 5m et distance au point inscrite sur le panneau de 3m). 
  Une photo du point ou du panneau et une description générale des lieux serait aussi des informations importantes. 
  Enfin, il faudrait aussi prendre en note l'organisme propriétaire du point géodésique. Au Québec il en existe plusieurs: 
  Le Service de la géodésie du Québec, Ministère des Ressources naturelles, Québec 
- La Division des levés géodésiques, Géomatique Canada, Secteur des sciences de la terre Ressources naturelles Canada  
- Le Service hydrographique du Canada, Direction des sciences, Pêches et Océans Canada et la Garde côtière canadienne, Pêches et Océans Canada  
+ La Division des levés géodésiques, Géomatique Canada, Secteur des sciences de la terre Ressources naturelles Canada 
+ Le Service hydrographique du Canada, Direction des sciences, Pêches et Océans Canada et la Garde côtière canadienne, Pêches et Océans Canada 
  Et tout les anciens noms de ministères et/ou organisme 
  Des photos de points de même que des panneaux suivront bientôt. VOUS NE POUVEZ INSCRIRE QU'UN SEUL POINT GÉODÉSIQUE (UN POINT PAR GÉOCACHEUR) Bonne chance! 
- The goal of this virtual cache is to find the geodetic points of Québec’s territory. The geodetic points are easy to identify (Brass cap at ground level) Generally, there is an orange panel of on a post near the point. On this panel, the number of the point is identified. Also, the distance relating from the panel to the point is also indicated. In order to log your find, you must take in note THE NUMBER OF THE POINT(registered on the point or in the center of the panel) and THE COORDINATES(in format HDDD MM.MM WGS84 datum AND UTM NAD83 indicate the zone please)and THE ALTITUDE. If the point is not visible (it may be buried under few centimetres) you can take the coordinate at the panel IF THE ACCURACY OF YOUR GPS IS HIGHER Than the DISTANCE REGISTERED ON the PANEL. (Ex: accuracy of the GPS is 5m and the distance to the point registered on the panel is 3m).  
- A picture of the point or panel and a general description of the places would be also significant information. Finally, it would also be important to take in note the organization owner of the geodetic point.  In Quebec there are several:  
- The "Service de la géodésie du Québec, Ministère des Ressources naturelles Québec" The Geodetic Survey Division, Geomatics Canada, Earth Sciences Sector, Natural Resources Canada  The Canadian Hydrographic Service, Sciences Directorate, Fisheries and Oceans Canada and the Canadian Coast Guard, Fisheries and Oceans Canada And all old names of ministries and/or organization 
+ The goal of this virtual cache is to find the geodetic points of Québec’s territory. The geodetic points are easy to identify (Brass cap at ground level) Generally, there is an orange panel of on a post near the point. On this panel, the number of the point is identified. Also, the distance relating from the panel to the point is also indicated. In order to log your find, you must take in note THE NUMBER OF THE POINT(registered on the point or in the center of the panel) and THE COORDINATES(in format HDDD MM.MM WGS84 datum AND UTM NAD83 indicate the zone please)and THE ALTITUDE. If the point is not visible (it may be buried under few centimetres) you can take the coordinate at the panel IF THE ACCURACY OF YOUR GPS IS HIGHER Than the DISTANCE REGISTERED ON the PANEL. (Ex: accuracy of the GPS is 5m and the distance to the point registered on the panel is 3m). 
+ A picture of the point or panel and a general description of the places would be also significant information. Finally, it would also be important to take in note the organization owner of the geodetic point. In Quebec there are several: 
+ The "Service de la géodésie du Québec, Ministère des Ressources naturelles Québec" The Geodetic Survey Division, Geomatics Canada, Earth Sciences Sector, Natural Resources Canada The Canadian Hydrographic Service, Sciences Directorate, Fisheries and Oceans Canada and the Canadian Coast Guard, Fisheries and Oceans Canada And all old names of ministries and/or organization 
  PICTURES of points and of the panels will follow soon. YOU CAN ONLY LOG ONE POINT (ONE POINT PER GEOCACHER) Good luck!
 
 Found it by Christopher R & Pooh B on 2005-07-12
index ac6b2e75034f54223d634751b1c863522a67980d..96a309dd49ab7f4519c83355d178e327ec1bea85 100644 (file)
@@ -4,7 +4,7 @@ Oozy rat in a sanitary zoo by robertlipe - Unknown Cache / Unknown - (3 / 2)
 
 The cache is not at the coordinates above. These coords will get you to the correct park and within 1/2 mile of the cache. The cache is within 35 feet of the trail. It is not handicapped accessible. It is a nice walk in the woods that is practical for all ages. There is no space in the container for trading items. You should bring a writing stick and bug spray is recommended.
 
-So if the cache isn't at the above coordinates, where is it?   Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men," I nod Rats live on no evil star Go hang a salami, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is, turn on your geo-mojo and go find it. 
+So if the cache isn't at the above coordinates, where is it?  Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men," I nod Rats live on no evil star Go hang a salami, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is, turn on your geo-mojo and go find it. 
  [IMG]
  
 
index ac6b2e75034f54223d634751b1c863522a67980d..96a309dd49ab7f4519c83355d178e327ec1bea85 100644 (file)
@@ -4,7 +4,7 @@ Oozy rat in a sanitary zoo by robertlipe - Unknown Cache / Unknown - (3 / 2)
 
 The cache is not at the coordinates above. These coords will get you to the correct park and within 1/2 mile of the cache. The cache is within 35 feet of the trail. It is not handicapped accessible. It is a nice walk in the woods that is practical for all ages. There is no space in the container for trading items. You should bring a writing stick and bug spray is recommended.
 
-So if the cache isn't at the above coordinates, where is it?   Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men," I nod Rats live on no evil star Go hang a salami, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is, turn on your geo-mojo and go find it. 
+So if the cache isn't at the above coordinates, where is it?  Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men," I nod Rats live on no evil star Go hang a salami, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is, turn on your geo-mojo and go find it. 
  [IMG]
  
 
diff --git a/reference/gc/GCGCA8_nasty.gpx b/reference/gc/GCGCA8_nasty.gpx
new file mode 100644 (file)
index 0000000..ebcac66
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<gpx xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" creator="Groundspeak, Inc. All Rights Reserved. http://www.groundspeak.com" xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd http://www.groundspeak.com/cache/1/0/1 http://www.groundspeak.com/cache/1/0/1/cache.xsd" xmlns="http://www.topografix.com/GPX/1/0">\r
+  <name>Cache Listing Generated from Geocaching.com</name>\r
+  <desc>This is an individual cache generated from Geocaching.com</desc>\r
+  <author>Account "robertlipe" From Geocaching.com</author>\r
+  <email>contact@geocaching.com</email>\r
+  <url>https://www.geocaching.com</url>\r
+  <urlname>Geocaching - High Tech Treasure Hunting</urlname>\r
+  <time>2023-10-25T00:44:53.7176739Z</time>\r
+  <keywords>cache, geocache</keywords>\r
+  <bounds minlat="35.921667" minlon="-86.861667" maxlat="35.921667" maxlon="-86.861667" />\r
+  <wpt lat="35.921667" lon="-86.861667">\r
+    <time>2003-06-29T00:00:00</time>\r
+    <name>GCGCA8</name>\r
+    <desc>Oozy rat in a sanitary zoo by robertlipe, Unknown Cache (3/2)</desc>\r
+    <url>https://www.geocaching.com/geocache/GCGCA8</url>\r
+    <urlname>Oozy rat in a sanitary zoo</urlname>\r
+    <sym>Geocache</sym>\r
+    <type>Geocache|Unknown Cache</type>\r
+    <groundspeak:cache id="77386" available="False" archived="True" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">\r
+      <groundspeak:name>Oozy rat in a sanitary zoo</groundspeak:name>\r
+      <groundspeak:placed_by>robertlipe</groundspeak:placed_by>\r
+      <groundspeak:owner id="32733">robertlipe</groundspeak:owner>\r
+      <groundspeak:type>Unknown Cache</groundspeak:type>\r
+      <groundspeak:container>Not chosen</groundspeak:container>\r
+      <groundspeak:attributes>\r
+        <groundspeak:attribute id="24" inc="0">Wheelchair accessible</groundspeak:attribute>\r
+        <groundspeak:attribute id="19" inc="1">Ticks</groundspeak:attribute>\r
+        <groundspeak:attribute id="18" inc="1">Dangerous animals</groundspeak:attribute>\r
+        <groundspeak:attribute id="17" inc="1">Poisonous plants</groundspeak:attribute>\r
+        <groundspeak:attribute id="39" inc="1">Thorns</groundspeak:attribute>\r
+        <groundspeak:attribute id="30" inc="1">Picnic tables nearby</groundspeak:attribute>\r
+        <groundspeak:attribute id="28" inc="1">Public restrooms nearby</groundspeak:attribute>\r
+        <groundspeak:attribute id="1" inc="1">Dogs</groundspeak:attribute>\r
+      </groundspeak:attributes>\r
+      <groundspeak:difficulty>3</groundspeak:difficulty>\r
+      <groundspeak:terrain>2</groundspeak:terrain>\r
+      <groundspeak:country>United States</groundspeak:country>\r
+      <groundspeak:state>Tennessee</groundspeak:state>\r
+      <groundspeak:short_description html="True">&lt;body&gt;The cache is &lt;style&gt;\r
+not&lt;/style&gt; at the coordinates above. These coords will get\r
+you to the correct park and within 1/2 mile of the cache. The cache\r
+is within 35 feet of the trail. It is not handicapped accessible.\r
+It is a nice walk in the woods that is practical for all ages.\r
+There is no space in the container for trading items. You should\r
+bring a writing stick and bug spray is recommended.&lt;/body&gt;\r
+</groundspeak:short_description>\r
+      <groundspeak:long_description html="True">&lt;html&gt;&lt;body text="color"&gt;So if the cache isn't at the above coordinates, where is it? \r
+&lt;ul&gt;\r
+&lt;li&gt;Too bad I hid a boot&lt;/li&gt;\r
+&lt;li&gt;Too hot to hoot&lt;/li&gt;\r
+&lt;li&gt;Never odd or even&lt;/li&gt;\r
+&lt;li&gt;Do geese see God?&lt;/li&gt;\r
+&lt;li&gt;"Do nine men interpret?" "Nine men," I nod&lt;/li&gt;\r
+&lt;li&gt;Rats live on no evil star&lt;/li&gt;\r
+&lt;li&gt;Go hang a salami, I'm a lasagna hog&lt;/li&gt;&lt;/ul&gt;\r
+Now that it's intuitively obvious to even the most casual observer\r
+where the cache is, turn on your geo-mojo and go find it. &lt;br&gt;\r
+&lt;image src="http://www.mtgc.org/mtgc_member-banner.gif" width="500"\r
+height="40" alt=\r
+"Member of Middle Tennessee GeoCachers Club [www.mtgc.org]"\r
+     border="0"&gt;&lt;br&gt;\r
+&lt;br&gt;&lt;/body&gt;&lt;/html&gt;\r
+</groundspeak:long_description>\r
+      <groundspeak:encoded_hints>\r
+      </groundspeak:encoded_hints>\r
+      <groundspeak:logs>\r
+        <groundspeak:log id="732879189">\r
+          <groundspeak:date>2017-11-11T01:44:14Z</groundspeak:date>\r
+          <groundspeak:type>Archive</groundspeak:type>\r
+          <groundspeak:finder id="32733">robertlipe</groundspeak:finder>\r
+          <groundspeak:text encoded="False">Removed the container from the final location. Enough construction has occurred since this was placed to make it much less of an adventure than is used to be, so I'm archiving.
+
+Thanx to all that hunted it.</groundspeak:text>\r
+        </groundspeak:log>\r
+      </groundspeak:logs>\r
+      <groundspeak:travelbugs />\r
+    </groundspeak:cache>\r
+  </wpt>\r
+</gpx>
diff --git a/reference/gc/GCGCA8_nasty.html b/reference/gc/GCGCA8_nasty.html
new file mode 100644 (file)
index 0000000..d6c592c
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>GPSBabel HTML Output</title>
+  <style>
+    p.gpsbabelwaypoint { font-size: 120%; font-weight: bold }
+  </style>
+</head>
+<body>
+  <p class="index">
+    <a href="#WPT001">GCGCA8 - Oozy rat in a sanitary zoo</a><br>
+  </p>
+  <div id="WPT001"><hr>
+    <table style="width:100%">
+      <tr>
+        <td>
+          <p class="gpsbabelwaypoint">GCGCA8 - N35&deg;55.300 W86&deg;51.700 (16S 512480 3975269)<br>
+<a href="https://www.geocaching.com/geocache/GCGCA8">Oozy rat in a sanitary zoo</a> by robertlipe</p>
+        </td>
+        <td style="text-align:right">
+          <p class="gpsbabelcacheinfo">3 / 2<br>
+Unknown Cache / Unknown</p>
+        </td>
+      </tr>
+      <tr>
+        <td colspan="2">
+          <div><p class="gpsbabeldescshort">The cache is  at the coordinates above. These coords will get
+you to the correct park and within 1/2 mile of the cache. The cache
+is within 35 feet of the trail. It is not handicapped accessible.
+It is a nice walk in the woods that is practical for all ages.
+There is no space in the container for trading items. You should
+bring a writing stick and bug spray is recommended.</div>
+          <div><p class="gpsbabeldesclong">So if the cache isn't at the above coordinates, where is it? 
+<ul>
+<li>Too bad I hid a boot</li>
+<li>Too hot to hoot</li>
+<li>Never odd or even</li>
+<li>Do geese see God?</li>
+<li>"Do nine men interpret?" "Nine men," I nod</li>
+<li>Rats live on no evil star</li>
+<li>Go hang a salami, I'm a lasagna hog</li></ul>
+Now that it's intuitively obvious to even the most casual observer
+where the cache is, turn on your geo-mojo and go find it. <br>
+<img src="http://www.mtgc.org/mtgc_member-banner.gif" width="500"
+height="40" alt=
+"Member of Middle Tennessee GeoCachers Club [www.mtgc.org]"
+     border="0"><br>
+<br></div>
+        </td>
+      </tr>
+    </table>
+  </div>
+</body>
+</html>
index 1d94b1408b425640eb5a42297fb72f9ea86ae4ca..3ea25b26511c3cda1d5b9ef1cec03ee26f5b682d 100644 (file)
@@ -3,5 +3,5 @@ VERSION:3.0
 N:Oozy rat in a sanitary zoo;GCGCA8;;;
 ADR:N35 55.300 W86 51.700
 URL:https://www.geocaching.com/geocache/GCGCA8
-NOTE:The cache is not at the coordinates above. These coords will get you to the correct park and within 1/2 mile of the cache. The cache is within 35 feet of the trail. It is not handicapped accessible. It is a nice walk in the woods that is practical for all ages. There is no space in the container for trading items. You should bring a writing stick and bug spray is recommended.\nSo if the cache isn't at the above coordinates\, where is it?   Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men\," I nod Rats live on no evil star Go hang a salami\, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is\, turn on your geo-mojo and go find it. \n [IMG]\n \n\n\nHINT:\n
+NOTE:The cache is not at the coordinates above. These coords will get you to the correct park and within 1/2 mile of the cache. The cache is within 35 feet of the trail. It is not handicapped accessible. It is a nice walk in the woods that is practical for all ages. There is no space in the container for trading items. You should bring a writing stick and bug spray is recommended.\nSo if the cache isn't at the above coordinates\, where is it?  Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men\," I nod Rats live on no evil star Go hang a salami\, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is\, turn on your geo-mojo and go find it. \n [IMG]\n \n\n\nHINT:\n
 END:VCARD
diff --git a/testo b/testo
index fc55501629729f351bfac26d113ecf73aa3359af..5083eead1e89dff9713234b41a51e48adf8df645 100755 (executable)
--- a/testo
+++ b/testo
@@ -189,4 +189,5 @@ if [ -z "${VALGRIND}" ]; then
   fi
 fi
 
+echo "Total Errors: $errorcount"
 exit $errorcount
index e89b52226528354c275307a981c02609daaa7807..4307260bb9e2f1aa75ca08d5925e0c9ec06c0567 100644 (file)
@@ -16,3 +16,7 @@ gpsbabel -i gpx -f ${REFERENCE}/gc/GC7FA4.gpx \
   -o text,logs -F ${TMPDIR}/GC7FA4.text
 compare ${REFERENCE}/gc/GC7FA4.html ${TMPDIR}/GC7FA4.html
 compare ${REFERENCE}/gc/GC7FA4.text ${TMPDIR}/GC7FA4.text
+
+# GCGC8_nasty.gpx is hand modifed to test strip_nasty_html
+gpsbabel -i gpx -f ${REFERENCE}/gc/GCGCA8_nasty.gpx -o html -F ${TMPDIR}/GCGCA8_nasty.html
+compare ${REFERENCE}/gc/GCGCA8_nasty.html ${TMPDIR}/GCGCA8_nasty.html
index 426f2e5a2f86e97555de4ccc7ce71ab08e7c473d..bd03210df29147fdf68c9948214111ce961c75e6 100644 (file)
@@ -20,3 +20,7 @@ RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebeng
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
     dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+    dnf debuginfo-install --assumeyes qt6-qtbase && \
+    dnf clean all
index d1aa6cbd0dd355378c436b2d052706e5a498c2ae..bd26dbde54bc5c012fd63e924dfec1159c54e462 100644 (file)
@@ -20,3 +20,7 @@ RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebeng
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
     dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+    dnf debuginfo-install --assumeyes qt6-qtbase && \
+    dnf clean all
index 5d89d175f75c812683079d6d61878c6916b65ba8..c172680ac0def54542b33fdc4f0536891df0e611 100644 (file)
@@ -13,10 +13,12 @@ RUN dnf install --assumeyes git make valgrind diffutils findutils langpacks-en n
 RUN dnf install --assumeyes libusb1-devel zlib-devel shapelib-devel && \
     dnf clean all
 # Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
-    dnf clean all
 RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebengine-devel qt6-linguist qt6-qttranslations qt6-qt5compat-devel qt6-qttools-devel libxkbcommon-devel && \
     dnf clean all
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
     dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+    dnf debuginfo-install --assumeyes qt6-qtbase && \
+    dnf clean all
index fe9e83448ffd4309c67889e065ee723102d0a9e8..0f037c2c49c0b9a4d44db3d15da7ee6e6ef954ab 100644 (file)
@@ -13,10 +13,12 @@ RUN dnf install --assumeyes git make valgrind diffutils findutils langpacks-en n
 RUN dnf install --assumeyes libusb1-devel zlib-devel shapelib-devel && \
     dnf clean all
 # Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
-    dnf clean all
 RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebengine-devel qt6-linguist qt6-qttranslations qt6-qt5compat-devel qt6-qttools-devel libxkbcommon-devel && \
     dnf clean all
 # tools to build the docs
 RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
     dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+    dnf debuginfo-install --assumeyes qt6-qtbase && \
+    dnf clean all
index bd6b75b9b71aabd292aabcb63a38c601851ed36e..59671c31715d0e27692732ec61381d145e80b2b4 100644 (file)
@@ -89,6 +89,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
     qt6-wayland \
  && rm -rf /var/lib/apt/lists/*
 
+# dbgsyms for "libqt6core6/jammy-updates,now 6.2.4+dfsg-2ubuntu1.1 amd64" needed for gpsbabel.supp
+# these aren't on the debuginfod server, or on http://ddebs.ubuntu.com
+RUN curl -L http://launchpadlibrarian.net/638061995/libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64.ddeb -o libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64.ddeb \
+ && apt-get install ./libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64.ddeb \
+ && rm -f ./libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64
+
 # pkgs needed to generate coverage report:
 RUN apt-get update && apt-get install -y --no-install-recommends \
     gcovr \
index a96fa16839719eace2dde48a9bf0bb88eefdee43..ac01c7e9288b435f5d3930017f49b3f0f3b49e76 100644 (file)
@@ -71,6 +71,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
     qt6-wayland \
  && rm -rf /var/lib/apt/lists/*
 
+# dbgsyms for "libqt6core6t64/noble,now 6.4.2+dfsg-21.1build5 amd64" needed for gpsbabel.supp
+RUN apt-get update && apt-get install -y --no-install-recommends ubuntu-dbgsym-keyring \
+ && echo "deb http://ddebs.ubuntu.com noble main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list \
+ && echo "deb http://ddebs.ubuntu.com noble-updates main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list \
+ && echo "deb http://ddebs.ubuntu.com noble-proposed main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list \
+ && apt-get update && apt-get install -y --no-install-recommends libqt6core6t64-dbgsym \
+ && rm -rf /var/lib/apt/lists/*
+
 # pkgs needed to generate coverage report:
 RUN apt-get update && apt-get install -y --no-install-recommends \
     gcovr \
diff --git a/util.cc b/util.cc
index 7840d5268a16b8a67b479db661885e95ca374ca9..4259d345f88998663dd971c68d64f77e1f2aeba2 100644 (file)
--- a/util.cc
+++ b/util.cc
@@ -20,7 +20,7 @@
  */
 
 #include <algorithm>                    // for sort
-#include <cctype>                       // for isspace, tolower
+#include <cassert>                      // for assert
 #include <cerrno>                       // for errno
 #include <climits>                      // for INT_MAX, INT_MIN
 #include <cmath>                        // for fabs, floor
@@ -35,6 +35,9 @@
 #include <QDateTime>                    // for QDateTime
 #include <QFileInfo>                    // for QFileInfo
 #include <QList>                        // for QList
+#include <QRegularExpression>               // for QRegularExpression
+#include <QRegularExpressionMatch>          // for QRegularExpressionMatch
+#include <QRegularExpressionMatchIterator>  // for QRegularExpressionMatchIterator
 #include <QString>                      // for QString
 #include <QTextBoundaryFinder>          // for QTextBoundaryFinder, QTextBoundaryFinder::Grapheme
 #include <QTextCodec>                   // for QTextCodec
@@ -734,92 +737,29 @@ pretty_deg_format(double lat, double lon, char fmt, const char* sep, bool html)
 /*
  * Get rid of potentially nasty HTML that would influence another record
  * that includes;
- * <body> - to stop backgrounds/background colours from being loaded
+ * <body> - to stop backgrounds/background colors from being loaded
  * </body> and </html>- stop processing altogether
  * <style> </style> - stop overriding styles for everything
  */
 QString
 strip_nastyhtml(const QString& in)
 {
-  char* returnstr = xstrdup(in);
-  char* lcstr = xstrdup(in.toLower());
-
-  while (char* lcp = strstr(lcstr, "<body>")) {
-    char* sp = returnstr + (lcp - lcstr) ; /* becomes <!   > */
-    sp++;
-    *sp++ = '!';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *lcp = '*';         /* so we wont find it again */
-  }
-  while (char* lcp = strstr(lcstr, "<body")) {   /* becomes <!--        --> */
-    char* sp = returnstr + (lcp - lcstr) ;
-    sp++;
-    *sp++ = '!';
-    *sp++ = '-';
-    *sp++ = '-';
-    while ((*sp) && (*sp != '>')) {
-      sp++;
-    }
-    *--sp = '-';
-    *--sp = '-';
-    *lcp = '*';         /* so we wont find it again */
-  }
-  while (char* lcp = strstr(lcstr, "</body>")) {
-    char* sp = returnstr + (lcp - lcstr) ; /* becomes <!---- */
-    sp++;
-    *sp++ = '!';
-    *sp++ = '-';
-    *sp++ = '-';
-    *sp++ = '-';
-    *sp++ = '-';
-    *lcp = '*';         /* so we wont find it again */
-  }
-  while (char* lcp = strstr(lcstr, "</html>")) {
-    char* sp = returnstr + (lcp - lcstr) ; /* becomes </---- */
-    sp++;
-    *sp++ = '!';
-    *sp++ = '-';
-    *sp++ = '-';
-    *sp++ = '-';
-    *sp++ = '-';
-    *lcp = '*';         /* so we wont find it again */
-  }
-  while (char* lcp = strstr(lcstr, "<style")) {
-    char* sp = returnstr + (lcp - lcstr) ; /* becomes <!--   */
-    sp++;
-    *sp++ = '!';
-    *sp++ = '-';
-    *sp++ = '-';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *sp = ' ';
-    *lcp = '*';         /* so we wont find it again */
-  }
-  while (char* lcp = strstr(lcstr, "</style>")) {
-    char* sp = returnstr + (lcp - lcstr) ; /* becomes    --> */
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *sp++ = '-';
-    *sp++ = '-';
-    *lcp = '*';         /* so we wont find it again */
-  }
-  while (char* lcp = strstr(lcstr, "<image")) {
-    char* sp = returnstr + (lcp - lcstr) ; /* becomes <img */
-    sp+=3;
-    *sp++ = 'g';
-    *sp++ = ' ';
-    *sp++ = ' ';
-    *lcp = '*';
-  }
-  xfree(lcstr);
-  QString rv(returnstr);
-  xfree(returnstr);
-  return rv;
+  static const QRegularExpression htmlre("<html.*?>", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+  assert(htmlre.isValid());
+  static const QRegularExpression bodyre("<body.*?>", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+  assert(bodyre.isValid());
+  static const QRegularExpression stylere("<style.*?>.*?</style>", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+  assert(stylere.isValid());
+  QString out(in);
+
+  out.replace(bodyre, "");
+  out.replace("</body>", "", Qt::CaseInsensitive);
+  out.replace(htmlre, "");
+  out.replace("</html>", "", Qt::CaseInsensitive);
+  out.replace(stylere, "");
+  out.replace("<image", "<img", Qt::CaseInsensitive);
+
+  return out;
 }
 
 /*
@@ -838,82 +778,55 @@ QString strip_html(const QString& utfstring)
   doc.setHtml(utfstring);
   return doc.toPlainText().simplified();
 #else
-  char* out;
-  char* instr;
-  char tag[8];
-  unsigned short int taglen = 0;
-
-  char* incopy = instr = xstrdup(utfstring);
-  /*
-   * We only shorten, so just dupe the input buf for space.
-   */
-  char* outstring = out = xstrdup(utfstring);
-
-  tag[0] = 0;
-  while (*instr) {
-    if ((*instr == '<') || (*instr == '&')) {
-      tag[0] = *instr;
-      taglen = 0;
+  static const QRegularExpression re("(?:<(?<tag>[^ >]*).*?>)|(?:&(?<entity>.*?);)|(?<other>[^<&]+)|(?<fragment>.+)",
+                                     QRegularExpression::DotMatchesEverythingOption);
+  assert(re.isValid());
+  static const QRegularExpression newlinespace_re(R"(\s*\n\s*)");
+  assert(newlinespace_re.isValid());
+  QString out;
+
+  QRegularExpressionMatchIterator it = re.globalMatch(utfstring);
+  while (it.hasNext()) {
+    auto match = it.next();
+    //qDebug() << match.capturedTexts();
+    // TODO: Qt >= 6.3 use match.hasCaptured(...) instead of !match.captured(...).isNull()
+    if (!match.captured(u"tag").isNull()) {
+      QString tag = match.captured(u"tag");
+      //qDebug() << "tag match:" << tag;
+      if ((tag.compare("p", Qt::CaseInsensitive) == 0) ||
+          (tag.compare("br", Qt::CaseInsensitive) == 0) ||
+          (tag.compare("/tr", Qt::CaseInsensitive) == 0)) {
+        out.append('\n');
+      } else if (tag.compare("/td", Qt::CaseInsensitive) == 0) {
+        out.append(' ');
+      } else if (tag.startsWith("img", Qt::CaseInsensitive)) {
+        out.append("[IMG]");
+      } // else eat the tag
+    } else if (!match.captured(u"entity").isNull()) {
+      QString entity = match.captured(u"entity");
+      //qDebug() << "entity match:" << entity;
+      if (entity == "amp") {
+        out.append('&');
+      } else if (entity == "lt") {
+        out.append('<');
+      } else if (entity == "gt") {
+        out.append('>');
+      } else if (entity == "quot") {
+        out.append('"');
+      } else if (entity == "nbsp") {
+        out.append(' ');
+      } else if (entity == "deg") {
+        out.append("deg");
+      } // else eat the entity
+    } else if (!match.captured(u"other").isNull()) {
+      //qDebug() << "other match:" << match.capturedTexts();
+      out.append(match.captured(u"other").replace(newlinespace_re, " "));
+    //} else {
+    //  qDebug() << "unexpected fragment:" << match.capturedTexts();
     }
-
-    if (! tag[0]) {
-      if (*instr == '\n') {
-        *out++ = ' ';
-        do {
-          instr++;
-        } while (isspace(*instr));
-        continue;
-      } else {
-        *out++ = *instr;
-      }
-    } else {
-      if (taglen < (sizeof(tag)-1)) {
-        tag[taglen++] = tolower(*instr);
-        tag[taglen] = 0;
-      }
-    }
-
-    if (((tag[0] == '<') && (*instr == '>')) ||
-        ((tag[0] == '&') && (*instr == ';'))) {
-      if (! strcmp(tag, "&amp;")) {
-        *out++ = '&';
-      } else if (! strcmp(tag, "&lt;")) {
-        *out++ = '<';
-      } else if (! strcmp(tag, "&gt;")) {
-        *out++ = '>';
-      } else if (! strcmp(tag, "&quot;")) {
-        *out++ = '"';
-      } else if (! strcmp(tag, "&nbsp;")) {
-        *out++ = ' ';
-      } else if (! strcmp(tag, "&deg;")) {
-        *out++ = 'd';
-        *out++ = 'e';
-        *out++ = 'g';
-      } else if ((tag[0]=='<') && (tag[1]=='p')) {
-        *out++ = '\n';
-      } else if ((tag[0]=='<') && (tag[1]=='b') && (tag[2]=='r')) {
-        *out++ = '\n';
-      } else if ((tag[0]=='<') && (tag[1]=='/') && (tag[2]=='t') && (tag[3]=='r')) {
-        *out++ = '\n';
-      } else if ((tag[0]=='<') && (tag[1]=='/') && (tag[2]=='t') && (tag[3]=='d')) {
-        *out++ = ' ';
-      } else if ((tag[0]=='<') && (tag[1]=='i') && (tag[2]=='m') && (tag[3]=='g')) {
-        *out++ = '[';
-        *out++ = 'I';
-        *out++ = 'M';
-        *out++ = 'G';
-        *out++ = ']';
-      }
-
-      tag[0] = 0;
-    }
-    instr++;
   }
-  *out++ = 0;
-  xfree(incopy);
-  QString rv(outstring);
-  xfree(outstring);
-  return rv;
+
+  return out;
 #endif
 }